package gvo.search;

import gvo.basicDatatypes.GVOall;
import gvo.dbinfo.SarFieldInfo;
import gvo.dbinfo.TableInfo;
import gvo.presets.Presets;
import gvo.util.DelayedDocumentListener;
import gvo.util.GVOstore;
import gvo.util.SimpleFilter;

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.WindowConstants;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.apache.commons.io.output.FileWriterWithEncoding;
import org.jdesktop.swingworker.SwingWorker;

import com.Ostermiller.util.ExcelCSVPrinter;


public class SearchBiblio extends JFrame implements KeyListener, DocumentListener, ActionListener {
	private JList liste;
	private JFrame f2;
	private GVOstore gvostore;
	private JComboBox  fCombo, aCombo, sCombo;
	private JTextField search;
	
	private static final String SAVE = "save";
	private  JCheckBox leftStar, rightStar, listOnce;
	private SarFieldInfo[] ciField;
	private TableInfo ti;
	private final DefaultListModel model1 = new DefaultListModel();
	public static final String TSTRING = "Suche Quelle";
	protected static final int sortWidth = 300;
	protected static final int sortHeight = 450;
	protected static final int sortTop = 220;
	protected static final int sortLeft = 150;
	private String searchquery = "";
	private SwingWorker<ArrayList<ListEntry>, Void> worker = null;
	protected static final String UTF8 = "UTF-8"; 
	protected static final String UTF16 = "UTF-16"; 
	protected static final String ISO_8859_1 = "ISO-8859-1"; 
	public SearchBiblio(GVOstore gvostore) {
		super(TSTRING);
		this.setResizable(true);
		this.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
		f2 = this;
		this.gvostore = gvostore;
		createTable();
		getContentPane().add(BorderLayout.CENTER, createSearchPanel());
		getContentPane().add(BorderLayout.NORTH, createButtonPanel());
		//this.pack();
		this.setLocation(sortLeft, sortTop);
		this.setSize(sortWidth, sortHeight);
		this.setVisible(true);
	}

	private void createTable() {
		ti = gvostore.getDbInfo().findTable("V_ALL");
		int size = ti.fields.size();
		ciField = new SarFieldInfo[size];
		
		Iterator<SarFieldInfo> it = ti.fields.iterator();
		int i=0;
		while(it.hasNext()){
			ciField[i] = it.next();
			i++;
		}
		/*
		for (int i = 0; i < size; i++) {
			ciField[i] = ti.fields.iterator().get(i);
		}
		*/
	}
	public JPanel createButtonPanel(){
		JPanel buttonP = new JPanel();
		buttonP.setLayout(new GridLayout(1,3));
		JButton saveB = new JButton("Speichern");
		saveB.setActionCommand(SAVE);
		saveB.addActionListener(this);
		buttonP.add(saveB);
		//buttonP.add(new JLabel("2"));
		//buttonP.add(new JLabel("3"));
		return buttonP;
	}
	public JPanel createSearchPanel(){
		JPanel searchP = new JPanel();
		searchP.setLayout(new GridBagLayout());
		Insets ins = new Insets(0, 0, 0, 0);
		int reihe1=0;
		int reihe2=1;
		int reihe3=2;
		int reihe4=3;
		
		int w_sm=1;
		int w_med=2;
		int w_lg=4;
		int posy = 0;
		int h_norm=1;
		int h_lg=16;
		double pComb=0.5;
		double pLabc=0.5;
		double pLabs=0.0;
		double pMax = 1.0;
		if(gvostore.pre.isComplSearch()){
			listOnce =  new JCheckBox("DS nur einmal auflisten", true);
			//listOnce.setHorizontalAlignment(SwingConstants.RIGHT); 
			//listOnce.setHorizontalTextPosition(SwingConstants.LEADING);
			searchP.add(listOnce,new GridBagConstraints(reihe1, posy, w_lg, h_norm, pMax, 0.0,
				GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,ins, 0, 0));
			posy++;
		}
		JLabel anzTitel = new JLabel(" anzeigen:");
		searchP.add(anzTitel,new GridBagConstraints(reihe1, posy, w_med, h_norm, pLabc, 0.0,
				GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,ins, 0, 0));
		aCombo = new JComboBox(ciField);
		SarFieldInfo sfi = ti.getField(gvostore.pre.getStartAnzeigefeld());
		if(sfi==null){
			aCombo.setSelectedIndex(0);
		} else {
			aCombo.setSelectedItem(sfi);
		}
		searchP.add(aCombo,new GridBagConstraints(reihe3, posy, w_sm, h_norm, pComb, 0.0,
				GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,ins, 0, 0));
		
		posy++;
		JLabel sortTitel = new JLabel(" sortieren:");
		searchP.add(sortTitel,new GridBagConstraints(reihe1, posy, w_med, h_norm, pLabc, 0.0,
				GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,ins, 0, 0));
		sCombo = new JComboBox(ciField);
		sfi = ti.getField(gvostore.pre.getStartSortierfeld());
		if(sfi==null){
			sCombo.setSelectedIndex(0);
		} else {
			sCombo.setSelectedItem(sfi);
		}
		searchP.add(sCombo,new GridBagConstraints(reihe3, posy, w_sm, h_norm, pComb, 0.0,
				GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,ins, 0, 0));
		
		posy++;
		JLabel searTitel = new JLabel(" suchen:");
		searchP.add(searTitel,new GridBagConstraints(reihe1, posy, w_med, h_norm, pLabc, 0.0,
				GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,ins, 0, 0));
		fCombo = new JComboBox(ciField);
		sfi = ti.getField(gvostore.pre.getStartSuchfeld());
		if(sfi==null){
			fCombo.setSelectedIndex(0);
		} else {
			fCombo.setSelectedItem(sfi);
		}
		searchP.add(fCombo,new GridBagConstraints(reihe3, posy, w_sm, h_norm, pComb, 0.0,
				GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,ins, 0, 0));
		
		posy++;
		leftStar =  new JCheckBox("*", true);
		leftStar.setHorizontalAlignment(SwingConstants.RIGHT); 
		leftStar.setHorizontalTextPosition(SwingConstants.LEADING);
		searchP.add(leftStar,new GridBagConstraints(reihe1, posy, w_sm, h_norm, pLabs, 0.0,
				GridBagConstraints.WEST, GridBagConstraints.NONE,ins, 0, 0));
		search = new JTextField();
		search.getDocument().addDocumentListener(new DelayedDocumentListener(this, gvostore.pre.getDelay()));
		search.addKeyListener(this);
;		searchP.add(search,new GridBagConstraints(reihe2, posy, w_med, h_norm, pMax, 0.0,
				GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,ins, 0, 0));
		rightStar = new JCheckBox("*", true);
		searchP.add(rightStar,new GridBagConstraints(reihe4, posy, w_sm, h_norm, pLabs, 0.0,
				GridBagConstraints.WEST, GridBagConstraints.NONE,ins, 0, 0));
		
		posy++;
		liste = new JList(model1);
		ListSelectionModel listSelectionModel;
		listSelectionModel = liste.getSelectionModel();
		listSelectionModel.addListSelectionListener(new myListSelectionHandler());
		liste.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		JScrollPane scrListe = new JScrollPane(liste);
		searchP.add(scrListe,new GridBagConstraints(reihe1, posy, w_lg, h_lg, pMax, 1.0,
				GridBagConstraints.WEST, GridBagConstraints.BOTH,ins, 0, 0));
		return searchP;
	}
	public void setSuchErg(String titel, int anzErg, int anz) {
		f2.setTitle(titel + " (" + anzErg + " von " + anz + ")");
	}


	private String createQuery() {
		SarFieldInfo si = (SarFieldInfo) fCombo.getSelectedItem();
		String res = "SELECT idBuch, "+((SarFieldInfo)aCombo.getSelectedItem()).fieldName +" FROM V_All";

		
		
		
		
		String fiCl = si.createWhereString(search.getText(), leftStar.isSelected(), rightStar.isSelected());
		if (fiCl != null) {
			res = res +   " WHERE " + fiCl;
		}
		res +=  " ORDER BY " + sCombo.getSelectedItem();
		return res;
	}

	private void searchIt() {

		String query = createQuery();
		/*
		if (searchquery.equals(query) ){
			return;
		}
		*/
		searchquery = query;
		//System.out.println("sQuery : "+ query);
		
		model1.clear();
		model1.addElement(new ListEntry(Presets.NOID, "Suche ..."));
		f2.setTitle(TSTRING);
		
		if(worker !=null){
			//System.out.println("interrupt!");
			worker.cancel(true);
			worker = null;
		}
		worker = new SwingWorker<ArrayList<ListEntry>, Void>() {
			
			
			@Override
			protected ArrayList<ListEntry> doInBackground() throws Exception {
				//System.out.println("Thread start");
				boolean listone = true;
				if(gvostore.pre.isComplSearch()){
					listone = listOnce.isSelected();
				} 
				ArrayList<ListEntry> list = gvostore.sqlTool.searchVAll(searchquery, (SarFieldInfo)aCombo.getSelectedItem(),listone);
				//System.out.println("Thread ende");
				return list;
			}
			public void done() {
				if(this.isCancelled()){
					//System.out.println("Thread ist cancelled!");
					return;
				}
				ArrayList<ListEntry> list;
				try {
					list = get();
					model1.clear();
					//System.out.println("Start filling");
					f2.setTitle(TSTRING + " (" + list.size() +")" );
					Iterator<ListEntry> it = list.iterator();
					while (it.hasNext()) {
						model1.addElement(it.next());
					}
					//System.out.println("Ende filling");
				} catch (InterruptedException e) {
					e.printStackTrace();
				} catch (ExecutionException e) {
					e.printStackTrace();
				}
				
			}
			
		};
		worker.execute();
	}

	private class myListSelectionHandler implements ListSelectionListener {
		public void valueChanged(ListSelectionEvent e) {
			if (e.getValueIsAdjusting()) {
				return;
			}

			int index = liste.getSelectedIndex();
			int idBuch = -1;
			if (index >= 0) {
				//System.out.println(" -- " + index + " -- ");
				ListEntry t_data = (ListEntry) liste.getModel().getElementAt(index);
				idBuch = t_data.idBuch;
				//System.out.println(" -- " + index + " -- "+ idBuch);
			}
			if (idBuch == -1)
				return;
			gvostore.getGvoGUI().setDS(idBuch);
			/*
			if (!gv.quellenFenster.setDS(VarStor.KEINE_POS, id))
				JOptionPane.showMessageDialog(f, "der Datensatz mit der ID "
						+ id + " wurde nicht mehr gefunden!",
						"Datenbank Fehler", JOptionPane.WARNING_MESSAGE);
			 */
		}
	}
	public void keyPressed(KeyEvent e) {
		//System.out.println("KEP "+ e.getKeyChar() + " "+ e.getKeyCode());
		if(e.getKeyCode()==KeyEvent.VK_ENTER){
			searchIt();
		}
	}

	public void keyReleased(KeyEvent e) {
		//System.out.println("KER "+ e.getKeyChar() + " "+ e.getKeyCode());
		
	}

	public void keyTyped(KeyEvent e) {
		//System.out.println("KET "+ e.getKeyChar() + " "+ e.getKeyCode());
		
		
	}

	public void changedUpdate(DocumentEvent e) {
		//System.out.println("changed Update");
    	searchIt(); 
		
	}

	public void insertUpdate(DocumentEvent e) {
		//System.out.println("insert Update");
    	searchIt(); 
		
	}

	public void removeUpdate(DocumentEvent e) {
		//System.out.println("remove Update");
    	searchIt(); 
		
	}

	public void actionPerformed(ActionEvent e) {
		String cmd = e.getActionCommand();
		if(SAVE.equals(cmd)){
			File fd = saveFile();
			writeCSV(fd);
		}
	}
	public void writeCSVenc(File fd){
		
		try {
			FileWriterWithEncoding fwwe = new FileWriterWithEncoding(fd, "");
	
			fwwe.write(" ");
		} catch (IOException e) {
			GVOstore.showMessage("IOException: " + e.getMessage(), Level.WARNING, SearchBiblio.class.getName());

		}
	}
	public void writeCSV(File fd){
		BufferedWriter f;
		if (fd != null) {
			 
			try { 
				f = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fd),UTF8));
				ExcelCSVPrinter ecsvp = new ExcelCSVPrinter(f);
				ecsvp.setLineEnding("\r\n");
				ListEntry t_data;
				boolean first = true;
				GVOall gvoall;
				for (int i = 0; i < model1.getSize(); i++) {
					t_data = (ListEntry) liste.getModel().getElementAt(i);
					gvoall = gvostore.sqlTool.loadGVOallforId(t_data.idBuch);
					if (first) {
						ecsvp.writeln(gvoall.csvTitel());
						first = false;
					}
					ecsvp.writeln(gvoall.csvValues());
				}
				ecsvp.close();
			} catch (UnsupportedEncodingException e) {
				GVOstore.showMessage("EncodingError: " + e.getMessage(), Level.WARNING, SearchBiblio.class.getName());
			} catch (FileNotFoundException e) {
				GVOstore.showMessage("FileNotFound: " + e.getMessage(), Level.WARNING, SearchBiblio.class.getName());
			} catch (IOException e) {
				GVOstore.showMessage("IOException: " + e.getMessage(), Level.WARNING, SearchBiblio.class.getName());
			}
		}
	}
	public File saveFile() {
		JFileChooser m_chooser = new JFileChooser();
		SimpleFilter m_csvFilter = new SimpleFilter("csv", "csv Dokumente");
		m_chooser.setFileFilter(m_csvFilter);
		try {
			File dir = (new File(".")).getCanonicalFile();
			m_chooser.setCurrentDirectory(dir);
		} catch (IOException ex) {
			GVOstore.showMessage("IOException: " + ex.getMessage(), Level.WARNING, SearchBiblio.class.getName());

		}
		if (m_chooser.showSaveDialog(this) != JFileChooser.APPROVE_OPTION)
			return null;
		File f = m_chooser.getSelectedFile();
		if (f == null)
			return null;
		
		String FN = f.getPath();
		if (!FN.endsWith(".csv")) {
			FN = FN + ".csv";
			f = new File(FN);
		}
		return f;
	}
}

